#include <cassert>
#include <vector>

#include "StackAllocator.h"
#include "Config.h"


namespace MemMgr
{

StackAllocator::StackAllocator(void* iPoolPtr, const size_t iPoolSize)
{
	mBasePtr = static_cast<PtrType>(iPoolPtr);
	mTopPtr = mBasePtr + iPoolSize;
	mLowerStackPtr = mBasePtr;
	mUpperStackPtr = mTopPtr;
}


StackAllocator::~StackAllocator(void)
{
}


void* StackAllocator::Allocate(const size_t iSize, const StackAllocator::Marker iMarker)
{
	assert((mUpperStackPtr - mLowerStackPtr >= static_cast<int>(iSize)) && "Not enough memory");
	MarkerFields marker = iMarker;

	if(0 == marker.mStackNum)
	{
		assert(marker.mStackOffset <= static_cast<size_t>(mLowerStackPtr - mBasePtr));
		void* outPtr = mLowerStackPtr;
		mLowerStackPtr += iSize;
		return outPtr;
	}

	assert(marker.mStackOffset <= static_cast<size_t>(mTopPtr - mUpperStackPtr));
	void* outPtr = mUpperStackPtr;
	mUpperStackPtr -= iSize;
	return outPtr;
}


void StackAllocator::FreeToMarker(const StackAllocator::Marker iMarker)
{
	MarkerFields marker = iMarker;

	if(0 == marker.mStackNum)
	{
		assert(marker.mStackOffset <= static_cast<size_t>(mLowerStackPtr - mBasePtr));
		mLowerStackPtr = mBasePtr + marker.mStackOffset;
		return;
	}

	assert(marker.mStackOffset <= static_cast<size_t>(mTopPtr - mUpperStackPtr));
	mUpperStackPtr = mTopPtr - marker.mStackOffset;
}


StackAllocator::Marker StackAllocator::GetLowerStackMarker(void) const
{
	return MarkerFields(mLowerStackPtr - mBasePtr, 0);
}


StackAllocator::Marker StackAllocator::GetUpperStackMarker(void) const
{
	return MarkerFields(mTopPtr - mUpperStackPtr, 1);
}


void StackAllocator::Clear()
{
	mLowerStackPtr = mBasePtr;
	mUpperStackPtr = mTopPtr;
}

}